package com.wwg.yl;

import com.alibaba.fastjson.JSONObject;
import com.wwg.util.RestTemplateUtil;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.http.*;
import org.springframework.util.DigestUtils;
import org.springframework.web.client.RestTemplate;

import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class HttpTest {

    //最大线程数
    public static int maxThreadCount = 10;
    //线程池
    public static ExecutorService executorService = Executors.newFixedThreadPool(maxThreadCount);
    //全部任务列表
    public static List<Integer> taskList = new CopyOnWriteArrayList<>();
    //正在处理的任务列表
    public static List<Integer> curTaskList = new CopyOnWriteArrayList<>();
    //失败任务列表
    public static List<Integer> failTaskList = new CopyOnWriteArrayList<>();
    //记录已完成任务
    public static Map<Integer,Integer> successTaskMap = new HashMap<>();

    public static void main(String[] args) throws Exception {

        long startTime = System.currentTimeMillis();

//        String url = "http://10.254.124.140:8080/syncDoris/syncBySql";
        String url = "http://10.254.107.73:8080/syncDoris/syncBySql";
        //String url = "http://10.33.60.231:32341/syncDoris/syncBySql";
        String date = "2021-07-24";

        //检查当天任务是否已经完成,完成则退出
        //通过批次检查已同步的数据

        //初始化任务
        for (Integer i = -999; i <= 999; i++) {
            taskList.add(i);
        }

        //去掉已完成的任务批次
        //查询数据库已同步的批次

        boolean running = true;
        try {
            while (running) {

                for(Integer ci: curTaskList){
                    if(successTaskMap.containsKey(ci)){
                        curTaskList.remove(ci);
                        taskList.remove(ci);
                    }
                }

                System.out.println("—————当前剩余任务数: " + taskList.size() + ",失败任务数: " + failTaskList.size()+ ",正在执行任务数: " + curTaskList.size());

                //错误任务量太多,退出执行
                if(failTaskList.size() >= 10) {
                    System.out.println("—————任务停止执行,失败任务数:" + failTaskList.size());
                    executorService.shutdown();
                    running = false;
                }

                if (taskList.size() > 0) {

                    int addNewCount = 0;

                    //添加新任务（需要去除正在执行的任务，避免重复处理）
                    for (Integer i : taskList) {
                        boolean isExists = false;
                        for (Integer ci : curTaskList) {
                            if (ci == i) {
                                isExists = true;
                                break;
                            }
                        }

                        //新任务，处理
                        if (!isExists) {
                            if (curTaskList.size() < HttpTest.maxThreadCount) {
                                addNewCount++;
                                curTaskList.add(i);
                                executorService.execute(new RunnableThreadDemo(url, date, i));
                            }
                        }
                    }

                    System.out.println("—————新加" + addNewCount + " 个任务，当前正在执行的任务数:" + curTaskList.size());

                    //等待1秒执行
                    Thread.sleep(200);

                } else {
                    System.out.println("—————所有任务已完成:");
                    executorService.shutdown();
                    running = false;
                }
            }

            System.out.println("任务执行完成,总耗时 :" + (System.currentTimeMillis() - startTime) );
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public static JSONObject getClientParam(String date, int modNumber) {

        String userId = "ylnetworkmanage";
        String secretKey = "eWxuZXR3b3JrbWFuYWdlLXRlc3Q";
//
//        String sql = "SELECT send_shipment_no,pick_agent_name,start_center_name,pick_network_name,last_center_name,end_center_agent_name,end_center_name," +
//                "next_station_name,sign_provider_name,sign_city_name,sign_area_name,sign_network_name FROM \n" +
//                "  jms_dwd.dwd_centersend_timerate_detail t \n" +
//                "WHERE send_date = '" + date + "' \n" +
//                "  AND MOD(MURMUR_HASH3_32 (billcode), 1000) =" + modNumber;

//        MOD(MURMUR_HASH3_32(billcode), 5000) = #{batchNum}
        String sql = "SELECT ID, WAYBILL_NO, WAYBILL_STATUS_CODE, GOODS_TYPE_ID, GOODS_TYPE_CODE,GOODS_TYPE_NAME," +
                " GOODS_NAME, PACKAGE_NUMBER, PACKAGE_LENGTH, PACKAGE_WIDE PACKAGE_HIGH, PACKAGE_VOLUME, PACKAGE_TOTAL_WEIGHT, PACKAGE_TOTAL_VOLUME FROM" +
                "  jms_ods.yl_oms_oms_waybill t " +
                "WHERE 1=1 AND MOD(MURMUR_HASH3_32 (waybill_no), 5000) = #{batchNum}";

        RequestDTO requestDTO = new RequestDTO();
        String reqId = UUID.randomUUID().toString();
        requestDTO.setReqId(reqId);
        requestDTO.setUserId(userId);
        requestDTO.setTimestamp(System.currentTimeMillis());
        int batchNum = 1; //批次号
        Map<String,Object> p = new HashMap<>();
        p.put("sql",sql);
        p.put("batchNum",batchNum);
        p.put("date",date);
        requestDTO.setP(p);
        requestDTO.setSql(sql);

        StringBuffer mulParamStr = new StringBuffer();
        mulParamStr.append("userId=").append(userId);
        mulParamStr.append("&secretKey=").append(secretKey);
        mulParamStr.append("&reqId=").append(reqId);
        mulParamStr.append("&timestamp=").append(requestDTO.getTimestamp());
//        mulParamStr.append("&sql=").append(requestDTO.getSql());
        String md5Str = DigestUtils.md5DigestAsHex(mulParamStr.toString().getBytes());
        requestDTO.setSign(md5Str);

//        StringBuffer mulParamStr = new StringBuffer();
//        mulParamStr.append("userId=").append(userId);
//        mulParamStr.append("&secretKey=").append(secretKey);
//        mulParamStr.append("&reqId=").append(reqId);
//        mulParamStr.append("&timestamp=").append(requestDTO.getTimestamp());
//        String md5Str = DigestUtils.md5DigestAsHex(mulParamStr.toString().getBytes());
//        requestDTO.setSign(md5Str);



        return (JSONObject) JSONObject.toJSON(requestDTO);
    }

    private static class RequestDTO {
        private String reqId;
        private String userId;
        private long timestamp;
        private String sql;
        Map<String,Object> p;
        private String sign;

        public Map<String, Object> getP() {
            return p;
        }

        public void setP(Map<String, Object> p) {
            this.p = p;
        }

        public void setReqId(String reqId) {
            this.reqId = reqId;
        }

        public String getReqId() {
            return reqId;
        }

        public void setUserId(String userId) {
            this.userId = userId;
        }

        public String getUserId() {
            return userId;
        }

        public void setTimestamp(long timestamp) {
            this.timestamp = timestamp;
        }

        public long getTimestamp() {
            return timestamp;
        }

        public void setSql(String sql) {
            this.sql = sql;
        }

        public String getSql() {
            return sql;
        }

        public void setSign(String sign) {
            this.sign = sign;
        }

        public String getSign() {
            return sign;
        }
    }
}

class RunnableThreadDemo implements Runnable {

    private String url;
    private String date;
    private int modNum;

    public RunnableThreadDemo(String url, String date, int modNum) {
        this.url = url;
        this.date = date;
        this.modNum = modNum;
    }

    @Override
    public void run() {
        try {
            long startTime = System.currentTimeMillis();
            JSONObject clientParam = HttpTest.getClientParam(date, modNum);

//            RestTemplate restTemplate = new RestTemplate();
//            HttpHeaders httpHeaders = new HttpHeaders();
//            httpHeaders.setContentType(MediaType.APPLICATION_JSON);
//            httpHeaders.set("Accept",MediaType.APPLICATION_JSON_VALUE);
//            HttpEntity<String> httpEntity = new HttpEntity<>(clientParam.toJSONString(),httpHeaders);
//            ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.POST,httpEntity, String.class);
//            final String responseStr = responseEntity.getBody();

            String responseStr = RestTemplateUtil.post(url, clientParam.toJSONString(), String.class, 60 * 1000, 1);


//            String responseStr = rest.httpPost(url, HttpTest.getClientParam(date, modNum));
            if (null != responseStr) {
                JSONObject resultJson = (JSONObject) JSONObject.parse(responseStr);
                if (resultJson.getString("code").equals("1")) {
                    List<Map> resultDataList = resultJson.getObject("data", List.class);
                    System.out.println("i=" + modNum + "time:" + (System.currentTimeMillis() - startTime) + ",dataSize:" + resultDataList.size());
                    //insert to oracle

                    //标记任务已完成
                    System.out.println("i=" + modNum + " 任务执行完");
                    HttpTest.successTaskMap.put(modNum,1);
                } else {
                    HttpTest.failTaskList.add(modNum);
                    System.out.println("i=" + modNum + ",出错了,resultJson:" + resultJson);
                }
            }
        } catch (Exception e) {
            HttpTest.failTaskList.add(modNum);
            e.printStackTrace();
        }
    }

}